package com.uduemc.biso.node.web.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.utils.FileContentType;
import com.uduemc.biso.node.core.property.GlobalProperties;
import com.uduemc.biso.node.core.utils.SitePathUtil;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.component.wordfilter.CommonFilter;
import com.uduemc.biso.node.web.exception.NotFound404Exception;
import com.uduemc.biso.node.web.service.VirtualFolderService;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class VirtualFolderServiceImpl implements VirtualFolderService {

	@Autowired
	private GlobalProperties globalProperties;

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private CommonFilter commonFilter;

	@Override
	public boolean validFileUri(String fileUri) {

		File file = fileWithFileUri(fileUri);
		if (file == null) {
			return false;
		}

		return true;
	}

	@Override
	public File fileWithFileUri(String fileUri) {
		String makeFilePath = makeFilePath(fileUri);
		if (StrUtil.isBlank(makeFilePath)) {
			return null;
		}

		String filePath = URLUtil.decode(makeFilePath);
		File file = new File(filePath);
		if (!file.isFile()) {
			return null;
		}

		return file;
	}

	@Override
	public String makeFilePath(String fileUri) {
		if (StrUtil.isBlank(fileUri)) {
			log.error("用于生成完整文件路径的 fileUri 为空！");
			return null;
		}
		String basePath = globalProperties.getSite().getBasePath();
		Host host = requestHolder.getHost();
		String virtualFolderPath = SitePathUtil.getUserVirtualFolderPathByCode(basePath, host.getRandomCode());
		if (!FileUtil.isDirectory(virtualFolderPath)) {
			if (FileUtil.mkdir(virtualFolderPath) == null) {
				log.error("系统创建 " + virtualFolderPath + " 目录失败！");
				return null;
			}
		}
		if (StrUtil.isNotBlank(fileUri)) {
			fileUri = StrUtil.removePrefix(fileUri, "/");
			fileUri = StrUtil.removeSuffix(fileUri, "/");

			fileUri = StrUtil.removePrefix(fileUri, File.separator);
			fileUri = StrUtil.removeSuffix(fileUri, File.separator);

			virtualFolderPath = virtualFolderPath + File.separator + fileUri;
		}

		return virtualFolderPath;
	}

	@Override
	public void responseVirtualFolderFileUri(String fileUri, HttpServletResponse response) throws NotFound404Exception {
		File file = fileWithFileUri(fileUri);
		if (file == null) {
			return;
		}
		String contentType = FileContentType.contentType(file);
		if (StrUtil.isBlank(contentType)) {
			return;
		}

		// 定义需要过滤关键字的文件类型
		String[] cType = { "text/html", "text/plain" };

		FileInputStream openInputStream = null;
		try {
			openInputStream = FileUtils.openInputStream(file);

			if (openInputStream == null) {
				throw new NotFound404Exception("读取 VirtualFolder 文件失败！ fileUri: " + fileUri);
			}

			long size = FileUtil.size(file);
			response.setHeader("Accept-Ranges", "bytes");
			response.setHeader("Content-Length", "" + size);
			byte[] temp = new byte[(int) size];
			openInputStream.read(temp, 0, (int) size);
			OutputStream out = response.getOutputStream();
			response.setCharacterEncoding("utf-8");
			response.setContentType(contentType);
			if (ArrayUtil.contains(cType, contentType)) {
				String s = commonFilter.replace(StrUtil.str(temp, CharsetUtil.CHARSET_UTF_8));
				if (StrUtil.isBlank(s)) {
					s = "";
				}
				out.write(StrUtil.bytes(s));
			} else {
				out.write(temp);
			}

			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new NotFound404Exception("读取 VirtualFolder 文件失败！ fileUri: " + fileUri);
		} finally {
			if (openInputStream != null) {
				try {
					openInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
